package io.xxx.omni.osc.sync

import com.alibaba.fastjson.JSONObject
import io.xxx.omni.osc.common.toJSONObject
import io.xxx.omni.osc.common.toLocalDateTime
import io.xxx.omni.osc.common.zoneOffset
import io.xxx.omni.osc.domain.Document
import io.xxx.omni.osc.domain.DocumentType
import io.xxx.omni.osc.domain.PlatformIdentity
import io.xxx.omni.osc.domain.Store
import io.xxx.omni.osc.sdk.PddClient
import org.springframework.stereotype.Component
import java.time.Duration
import java.time.LocalDateTime

/**
 * 拼多多
 */
abstract class PddPorter : GenericPageDocumentPorter(), PlatformIdentity.PinDuoDuo {

    protected abstract val type: String

    override val duration: Duration = Duration.ofMinutes(30)

    override fun getResponse(context: JobContext, pageNo: Int, hasTotal: Boolean): JSONObject {
        val (store, startTime, endTime, parameter) = context
        val request = buildRequest(startTime, endTime, parameter, pageNo, hasTotal)
        val client = applicationContext.getBean(PddClient::class.java)
        val response = client.execute(store, type, request)
        val errorResponse = response.getJSONObject("error_response")
        if (errorResponse != null) {
            throwException(context, type, errorResponse)
        }
        return response
    }

    protected abstract fun buildRequest(
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        parameter: Any?,
        pageNo: Int,
        hasTotal: Boolean,
    ): Map<String, Any>
}

// 订单
// https://open.pinduoduo.com/application/document/api?id=pdd.order.number.list.increment.get
@Component
class PddTradePorter : PddPorter() {

    override val documentType = DocumentType.TRADE

    override val type = "pdd.order.number.list.increment.get"

    override fun getCount(context: JobContext, response: JSONObject): Int = response
        .getJSONObject("order_sn_increment_get_response")
        .getInteger("total_count")

    override fun buildDocuments(context: JobContext, response: JSONObject): List<Document> {
        return response
            .getJSONObject("order_sn_increment_get_response")
            .getJSONArray("order_sn_list")
            .map {
                val value = it.toJSONObject()
                val sn = value.getString("order_sn")
                val status = value.getString("status")
                val modified = value.getLong("updated_at").toLocalDateTime()
                Document(sn, status, modified, value)
            }
    }

    override fun buildRequest(
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        parameter: Any?,
        pageNo: Int,
        hasTotal: Boolean
    ): Map<String, Any> {
        return mapOf(
            "is_lucky_flag" to "0",
            "order_status" to "5",
            "start_updated_at" to startTime.toEpochSecond(zoneOffset),
            "end_updated_at" to endTime.toEpochSecond(zoneOffset),
            "page" to pageNo,
            "page_size" to pageSize,
            "use_has_next" to !hasTotal,
        )
    }
}

// 退单
// https://open.pinduoduo.com/application/document/api?id=pdd.refund.list.increment.get
@Component
class PddRefundPorter : PddPorter() {

    override val documentType = DocumentType.REFUND

    override val type = "pdd.refund.list.increment.get"

    override fun getParameters(store: Store) = listOf(
        0, 2, 3, 4, 5, 6, 7, 8, 9,
        10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 24, 25, 27,
        31, 32
    ) to true

    override fun getCount(context: JobContext, response: JSONObject): Int = response
        .getJSONObject("refund_increment_get_response")
        .getInteger("total_count")

    override fun buildDocuments(context: JobContext, response: JSONObject): List<Document> {
        return response
            .getJSONObject("refund_increment_get_response")
            .getJSONArray("refund_list")
            .map {
                val value = it.toJSONObject()
                val sn = value.getString("id")
                val rsn = value.getString("order_sn")
                val status = value.getString("status")
                val modified = value.getLong("updated_time").toLocalDateTime()
                Document(sn, rsn, status, modified, value)
            }
    }

    override fun buildRequest(
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        parameter: Any?,
        pageNo: Int,
        hasTotal: Boolean
    ): Map<String, Any> {
        return mapOf(
            "after_sales_status" to parameter!!,
            "after_sales_type" to 1,
            "start_updated_at" to startTime.toEpochSecond(zoneOffset),
            "end_updated_at" to endTime.toEpochSecond(zoneOffset),
            "page" to pageNo,
            "page_size" to pageSize,
        )
    }
}